package com.tools.service.workflow.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tools.mapper.workflow.StepExecutionMapper;
import com.tools.pojo.workflow.po.StepExecution;
import com.tools.service.workflow.StepExecutionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@RequiredArgsConstructor
public class StepExecutionServiceImpl extends ServiceImpl<StepExecutionMapper, StepExecution> implements StepExecutionService {


    private final ObjectMapper objectMapper;

    /**
     * 创建步骤执行记录
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<StepExecution> createStepExecutions(Long flowInstanceId, String flowConfig) {
        List<Map<String, Object>> stepsConfig = parseFlowConfig(flowConfig);
        List<StepExecution> stepExecutions = new ArrayList<>();

        for (int i = 0; i < stepsConfig.size(); i++) {
            Map<String, Object> stepConfig = stepsConfig.get(i);
            String stepCode = (String) stepConfig.get("stepCode");

            StepExecution execution = new StepExecution();
            execution.setFlowInstanceId(flowInstanceId);
            execution.setStepCode(stepCode);
            execution.setStepName((String) stepConfig.get("stepName"));
            execution.setExecuteOrder(i + 1);
            execution.setStatus(0); // 待执行
            execution.setInputData(serializeStepConfig(stepConfig));
            execution.setCreateTime(LocalDateTime.now());

            stepExecutions.add(execution);
        }

        saveBatch(stepExecutions);
        return stepExecutions;
    }

    /**
     * 获取待执行的步骤
     */
    @Override
    public List<StepExecution> getPendingSteps(Long flowInstanceId) {
        return lambdaQuery()
                .eq(StepExecution::getFlowInstanceId, flowInstanceId)
                .eq(StepExecution::getStatus, 0) // 待执行
                .orderByAsc(StepExecution::getExecuteOrder)
                .list();
    }

    /**
     * 获取流程实例的所有步骤执行记录
     */
    @Override
    public List<StepExecution> getByFlowInstanceId(Long flowInstanceId) {
        return lambdaQuery()
                .eq(StepExecution::getFlowInstanceId, flowInstanceId)
                .orderByAsc(StepExecution::getExecuteOrder)
                .list();
    }

    /**
     * 更新步骤状态为执行中
     */
    @Override
    public void updateStepStatus(Long stepExecutionId, Integer status, LocalDateTime startTime, LocalDateTime endTime) {
        StepExecution execution = new StepExecution();
        execution.setId(stepExecutionId);
        execution.setStatus(status);
        if (startTime != null) {
            execution.setStartTime(startTime);
        }
        if (endTime != null) {
            execution.setEndTime(endTime);
        }
        updateById(execution);
    }

    /**
     * 更新步骤执行成功
     */
    @Override
    public void updateStepSuccess(Long stepExecutionId, Object outputData, String message) {
        StepExecution execution = new StepExecution();
        execution.setId(stepExecutionId);
        execution.setStatus(2); // 成功
        execution.setOutputData(serializeOutputData(outputData));
        execution.setEndTime(LocalDateTime.now());
        updateById(execution);
    }

    /**
     * 更新步骤执行失败
     */
    @Override
    public void updateStepFailure(Long stepExecutionId, String errorMessage, boolean shouldCompensate) {
        StepExecution execution = new StepExecution();
        execution.setId(stepExecutionId);
        execution.setStatus(3); // 失败
        execution.setErrorMessage(errorMessage);
        execution.setEndTime(LocalDateTime.now());
        updateById(execution);
    }

    /**
     * 解析步骤配置
     */
    @Override
    public Map<String, Object> parseStepConfig(StepExecution stepExecution) {
        try {
            String configJson = stepExecution.getInputData();
            if (configJson == null || configJson.trim().isEmpty()) {
                return Map.of();
            }
            return objectMapper.readValue(configJson, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("解析步骤配置失败", e);
            return Map.of();
        }
    }

    /**
     * 获取失败的步骤执行记录
     */
    @Override
    public List<StepExecution> getFailedSteps(Long flowInstanceId) {
        return lambdaQuery()
                .eq(StepExecution::getFlowInstanceId, flowInstanceId)
                .eq(StepExecution::getStatus, 3) // 失败
                .list();
    }

    /**
     * 根据流程实例和步骤编码获取步骤执行记录
     */
    @Override
    public StepExecution getByFlowInstanceAndStepCode(Long flowInstanceId, String stepCode) {
        return lambdaQuery()
                .eq(StepExecution::getFlowInstanceId, flowInstanceId)
                .eq(StepExecution::getStepCode, stepCode)
                .one();
    }

    /**
     * 解析流程配置
     */
    private List<Map<String, Object>> parseFlowConfig(String flowConfig) {
        try {
            return objectMapper.readValue(flowConfig, new TypeReference<>() {
            });
        } catch (Exception e) {
            log.error("解析流程配置失败", e);
            throw new RuntimeException("流程配置格式错误", e);
        }
    }

    /**
     * 序列化步骤配置
     */
    private String serializeStepConfig(Map<String, Object> stepConfig) {
        try {
            return objectMapper.writeValueAsString(stepConfig);
        } catch (Exception e) {
            log.error("序列化步骤配置失败", e);
            return "{}";
        }
    }

    /**
     * 序列化输出数据
     */
    private String serializeOutputData(Object outputData) {
        try {
            return objectMapper.writeValueAsString(outputData);
        } catch (Exception e) {
            log.error("序列化输出数据失败", e);
            return "{}";
        }
    }

}
